package com.cskaoyan.market.service.impl;

import com.cskaoyan.market.db.admin.bo.creategoods.AdminGoodsDeleteBo;
import com.cskaoyan.market.service.AdminGoodsService;
import com.cskaoyan.market.db.admin.vo.BaseAdminGoodsInfoVo;
import com.cskaoyan.market.db.admin.vo.BrandVo;
import com.cskaoyan.market.db.admin.vo.CategoryVo;
import com.cskaoyan.market.db.common.BasePageInfo;
import com.cskaoyan.market.db.common.CommonData;
import com.cskaoyan.market.db.domain.*;
import com.cskaoyan.market.db.mapper.*;
import com.cskaoyan.market.util.MarketConstant;
import com.cskaoyan.market.util.MyBatisUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 小焦
 * @since 2023/03/21 09:16
 */
@Service
public class AdminGoodsServiceImpl implements AdminGoodsService {
    @Override
    public CommonData<MarketGoods> list(BasePageInfo basePageInfo, String goodsId, String goodsSn, String name) {
        SqlSession sqlSession = MyBatisUtil.getSession();
        MarketGoodsMapper goodsMapper = sqlSession.getMapper(MarketGoodsMapper.class);

        PageHelper.startPage(basePageInfo.getPage(), basePageInfo.getLimit());
        MarketGoodsExample goodsExample = new MarketGoodsExample();
        MarketGoodsExample.Criteria criteria = goodsExample.createCriteria();
        // 查询未被删除的数据
        criteria.andDeletedEqualTo(false);
        try {
            if (!StringUtils.isEmpty(goodsId)) {
                criteria.andIdEqualTo(Integer.valueOf(goodsId.trim()));
                // criteria.andGoodsSnLike(goodsSn).andGoodsSnIsNotNull();
            } else {
                if (!StringUtils.isEmpty(goodsSn)) {
                    // criteria.andIdEqualTo(Integer.valueOf(goodsId)).andIdIsNotNull();
                    criteria.andGoodsSnLike("%" + goodsSn.trim() + "%");
                }
                if (!StringUtils.isEmpty(name)) {
                    criteria.andNameLike("%" + name.trim() + "%");
                }
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return null;
        }
        goodsExample.setOrderByClause(basePageInfo.getSort() + " " + basePageInfo.getOrder());
        List<MarketGoods> marketGoods = goodsMapper.selectByExample(goodsExample);

        sqlSession.commit();
        sqlSession.close();
        PageInfo<MarketGoods> pageInfo = new PageInfo<>(marketGoods);
        CommonData<MarketGoods> data = CommonData.data(pageInfo);

        return data;

    }

    /**
     * 将这些数据存储到4张表 这4张表数据之间有没有关联呢？有，其余的三张表需要依赖于goods表，准确的说应该是其他三张表的数据需要依赖于goods表的编号goodsId
     * 
     * @param goods
     * @param specifications
     * @param products
     * @param attributes
     * @return
     */
    @Override
    public int addGoods(MarketGoods goods, MarketGoodsSpecification[] specifications, MarketGoodsProduct[] products,
        MarketGoodsAttribute[] attributes) {

        // 将goods的数据存储到商品表时，需要获取所有规格的最低价格，存储在retailPrice字段中
        BigDecimal retailPrice = new BigDecimal(Integer.MAX_VALUE);
        if (products != null) {
            retailPrice = products[0].getPrice();
        }
        BigDecimal counterPrice = goods.getCounterPrice();

        if (retailPrice != null && retailPrice.doubleValue() < 0) {
            return 405;
        }
        if (counterPrice != null && counterPrice.doubleValue() < 0) {
            return 405;
        }

        for (MarketGoodsProduct product : products) {
            // 遍历每一个规格的价格，找到最低的价格，赋值给retailPrice，进而存储到goods表中
            if (retailPrice.compareTo(product.getPrice()) == 1) {
                // retailPrice大于product.getPrice()
                retailPrice = product.getPrice();
            }
        }
        // 设置最小的价格，吸引他人点击你的商品
        goods.setRetailPrice(retailPrice);
        LocalDateTime now = LocalDateTime.now();
        goods.setAddTime(now);
        goods.setUpdateTime(LocalDateTime.now());
        goods.setDeleted(false);
        SqlSession sqlSession = MyBatisUtil.getSession();
        MarketGoodsMapper goodsMapper = sqlSession.getMapper(MarketGoodsMapper.class);
        MarketGoodsExample example = new MarketGoodsExample();
        MarketGoodsExample.Criteria criteria = example.createCriteria();
        criteria.andGoodsSnEqualTo(goods.getGoodsSn());
        List<MarketGoods> marketGoodsList = goodsMapper.selectByExample(example);
        if (marketGoodsList.size() > 0) {
            return 405;
        }

        MarketGoodsSpecificationMapper specificationMapper = sqlSession.getMapper(MarketGoodsSpecificationMapper.class);
        MarketGoodsProductMapper productMapper = sqlSession.getMapper(MarketGoodsProductMapper.class);
        MarketGoodsAttributeMapper attributeMapper = sqlSession.getMapper(MarketGoodsAttributeMapper.class);

        try {
            // 当我们执行完插入之后，我们再执行goods.getId便可以获取到商品的id
            goodsMapper.insertSelective(goods);
            // specificationMapper.insertSelective()
            Integer goodsId = goods.getId();
            for (MarketGoodsSpecification specification : specifications) {
                specification.setGoodsId(goodsId);
                specification.setDeleted(false);
                specification.setAddTime(now);
                specification.setUpdateTime(now);
                specificationMapper.insertSelective(specification);
            }
            for (MarketGoodsProduct product : products) {
                product.setGoodsId(goodsId);
                product.setAddTime(now);
                product.setUpdateTime(now);
                product.setDeleted(false);
                productMapper.insertSelective(product);
            }
            for (MarketGoodsAttribute attribute : attributes) {
                attribute.setGoodsId(goodsId);
                attribute.setAddTime(now);
                attribute.setUpdateTime(now);
                attribute.setDeleted(false);
                attributeMapper.insertSelective(attribute);
            }
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();
        } finally {
            sqlSession.close();
        }
        return 0;
    }

    @Override
    public Map<String, Object> catAndBrand() {
        // 先查询category，在查询brand
        SqlSession sqlSession = MyBatisUtil.getSession();
        MarketCategoryMapper categoryMapper = sqlSession.getMapper(MarketCategoryMapper.class);
        MarketCategoryExample categoryExample = new MarketCategoryExample();
        categoryExample.or().andDeletedEqualTo(false);
        List<MarketCategory> marketCategories = categoryMapper.selectByExample(categoryExample);

        MarketBrandMapper brandMapper = sqlSession.getMapper(MarketBrandMapper.class);
        MarketBrandExample marketBrandExample = new MarketBrandExample();
        marketBrandExample.or().andDeletedEqualTo(false);
        List<MarketBrand> marketBrands = brandMapper.selectByExample(marketBrandExample);
        sqlSession.commit();
        sqlSession.close();

        // 进一步去处理分类和品牌
        Map<Integer, List<MarketCategory>> listMap = groupByPid(marketCategories);
        List<MarketCategory> l1Categories = listMap.get(MarketConstant.MARKET_CATEGORY_LEVEL_1);
        List<CategoryVo> l1vos = new ArrayList<>();
        for (MarketCategory l1Category : l1Categories) {
            // 每个一级分类
            CategoryVo l1VO = new CategoryVo();
            l1VO.setLabel(l1Category.getName());
            l1VO.setValue(l1Category.getId());
            List<CategoryVo> l2vos = new ArrayList<>();
            List<MarketCategory> l2CategoriesOfL1 = listMap.get(l1Category.getId());
            for (MarketCategory l2 : l2CategoriesOfL1) {
                CategoryVo l2Vo = new CategoryVo();
                l2Vo.setValue(l2.getId());
                l2Vo.setLabel(l2.getName());
                l2vos.add(l2Vo);
            }
            l1VO.setChildren(l2vos);
            l1vos.add(l1VO);
        }
        // 处理品牌
        List<BrandVo> brandVos = new ArrayList<>();
        for (MarketBrand marketBrand : marketBrands) {
            BrandVo brandVo = new BrandVo();
            brandVo.setValue(marketBrand.getId());
            brandVo.setLabel(marketBrand.getName());
            brandVos.add(brandVo);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("categoryList", l1vos);
        result.put("brandList", brandVos);
        return result;
    }

    @Override
    public BaseAdminGoodsInfoVo detail(Integer id) {
        SqlSession sqlSession = MyBatisUtil.getSession();
        MarketGoodsMapper goodsMapper = sqlSession.getMapper(MarketGoodsMapper.class);
        BaseAdminGoodsInfoVo goodsInfoVo = new BaseAdminGoodsInfoVo();
        MarketGoods goods = goodsMapper.selectByPrimaryKey(id);
        goodsInfoVo.setGoods(goods);
        // -----------
        MarketGoodsAttributeMapper attributeMapper = sqlSession.getMapper(MarketGoodsAttributeMapper.class);
        MarketGoodsAttributeExample attributeExample = new MarketGoodsAttributeExample();
        attributeExample.createCriteria().andGoodsIdEqualTo(id);
        List<MarketGoodsAttribute> goodsAttributes = attributeMapper.selectByExample(attributeExample);
        goodsInfoVo.setAttributes(goodsAttributes);
        // ---------
        MarketGoodsSpecificationMapper specificationMapper = sqlSession.getMapper(MarketGoodsSpecificationMapper.class);
        MarketGoodsSpecificationExample specificationExample = new MarketGoodsSpecificationExample();
        specificationExample.createCriteria().andGoodsIdEqualTo(id);
        List<MarketGoodsSpecification> goodsSpecifications = specificationMapper.selectByExample(specificationExample);
        goodsInfoVo.setSpecifications(goodsSpecifications);
        // ---------
        MarketGoodsProductMapper productMapper = sqlSession.getMapper(MarketGoodsProductMapper.class);
        MarketGoodsProductExample goodsProductExample = new MarketGoodsProductExample();
        goodsProductExample.createCriteria().andGoodsIdEqualTo(id);
        List<MarketGoodsProduct> goodsProducts = productMapper.selectByExample(goodsProductExample);
        goodsInfoVo.setProducts(goodsProducts);

        MarketCategoryMapper categoryMapper = sqlSession.getMapper(MarketCategoryMapper.class);
        // <select id="selectIdByPid" resultType="java.lang.Integer">
        //
        // SELECT
        // mc1.id
        // FROM
        // market_category AS mc1
        // LEFT JOIN market_category AS mc2 ON mc1.id = mc2.pid
        // WHERE
        // mc2.id = #{pid}
        //
        // </select>
        Integer categoryPid = goods.getCategoryId();
        Integer categoryId = categoryMapper.selectIdByPid(categoryPid);
        goodsInfoVo.setCategoryIds(new Integer[] {categoryId, categoryPid});
        sqlSession.commit();
        sqlSession.close();

        return goodsInfoVo;
    }

    @Override
    public int updateGoods(MarketGoods goods, MarketGoodsSpecification[] specifications, MarketGoodsProduct[] products,
        MarketGoodsAttribute[] attributes, Integer[] categoryIds) {
        // 将goods的数据存储到商品表时，需要获取所有规格的最低价格，存储在retailPrice字段中
        BigDecimal retailPrice = new BigDecimal(Integer.MAX_VALUE);

        retailPrice = products[0].getPrice();
        BigDecimal counterPrice = goods.getCounterPrice();

        if (retailPrice != null && retailPrice.doubleValue() < 0) {
            return 405;
        }
        if (counterPrice != null && counterPrice.doubleValue() < 0) {
            return 405;
        }

        for (MarketGoodsProduct product : products) {
            // 遍历每一个规格的价格，找到最低的价格，赋值给retailPrice，进而存储到goods表中
            if (retailPrice.compareTo(product.getPrice()) == 1) {
                // retailPrice大于product.getPrice()
                retailPrice = product.getPrice();
            }
        }
        // 设置最小的价格，吸引他人点击你的商品
        goods.setRetailPrice(retailPrice);
        LocalDateTime now = LocalDateTime.now();
        goods.setAddTime(now);
        goods.setUpdateTime(LocalDateTime.now());
        goods.setDeleted(false);
        SqlSession sqlSession = MyBatisUtil.getSession();
        MarketGoodsMapper goodsMapper = sqlSession.getMapper(MarketGoodsMapper.class);
        MarketGoodsExample example = new MarketGoodsExample();
        MarketGoodsExample.Criteria criteria = example.createCriteria();
        criteria.andGoodsSnEqualTo(goods.getGoodsSn());
        List<MarketGoods> marketGoodsList = goodsMapper.selectByExample(example);
        if (marketGoodsList.size() > 0) {
            return 405;
        }

        MarketGoodsSpecificationMapper specificationMapper = sqlSession.getMapper(MarketGoodsSpecificationMapper.class);
        MarketGoodsProductMapper productMapper = sqlSession.getMapper(MarketGoodsProductMapper.class);
        MarketGoodsAttributeMapper attributeMapper = sqlSession.getMapper(MarketGoodsAttributeMapper.class);

        try {
            // 当我们执行完插入之后，我们再执行goods.getId便可以获取到商品的id
            goodsMapper.updateByPrimaryKeySelective(goods);
            Integer goodsId = goods.getId();
            // specificationMapper.insertSelective()
            for (MarketGoodsSpecification specification : specifications) {
                if (specification.getId() == null) {
                    specification.setGoodsId(goodsId);
                    specification.setAddTime(now);
                    specificationMapper.insert(specification);
                    continue;
                }
                specification.setUpdateTime(now);
                // MarketGoodsSpecificationExample specificationExample = new MarketGoodsSpecificationExample();
                // specificationExample.createCriteria().andGoodsIdEqualTo(specification.getGoodsId());
                // specificationMapper.updateByExampleSelective(specification, specificationExample);
                specificationMapper.updateByPrimaryKeySelective(specification);
            }
            for (MarketGoodsProduct product : products) {
                if (product.getId() == null) {
                    product.setGoodsId(goodsId);
                    product.setAddTime(now);
                    productMapper.insertSelective(product);
                    continue;
                }
                product.setUpdateTime(now);
                // MarketGoodsProductExample productExample = new MarketGoodsProductExample();
                // productExample.createCriteria().andGoodsIdEqualTo(product.getGoodsId());
                // productMapper.updateByExampleSelective(product, productExample);
                productMapper.updateByPrimaryKeySelective(product);
            }
            for (MarketGoodsAttribute attribute : attributes) {
                if (attribute.getId() == null) {
                    attribute.setGoodsId(goodsId);
                    attribute.setAddTime(now);
                    attributeMapper.insertSelective(attribute);
                    continue;
                }
                attribute.setUpdateTime(now);
                // MarketGoodsAttributeExample attributeExample = new MarketGoodsAttributeExample();
                // attributeExample.createCriteria().andGoodsIdEqualTo(attribute.getGoodsId());
                // attributeMapper.updateByExampleSelective(attribute, attributeExample);
                attributeMapper.updateByPrimaryKeySelective(attribute);
            }
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();
        } finally {
            sqlSession.close();
        }
        return 0;
    }

    @Override
    public int delete(AdminGoodsDeleteBo goods) {
        SqlSession sqlSession = MyBatisUtil.getSession();
        MarketGoodsMapper goodsMapper = sqlSession.getMapper(MarketGoodsMapper.class);
        try {
            goodsMapper.logicalDeleteByPrimaryKey(goods.getId());
        } catch (Exception e) {
            e.printStackTrace();
            return 405;
        }
        sqlSession.commit();
        sqlSession.close();
        return 0;
    }

    /**
     * 将list按照pid来进行分类，放入map中 再利用map.get(pid=0)可以获取到一级分类 在此基础上，我们再用map.get(一级分类的编号)便可以获取到对应的二级分类
     * 
     * @param marketCategories
     * @return
     */
    private Map<Integer, List<MarketCategory>> groupByPid(List<MarketCategory> marketCategories) {
        Map<Integer, List<MarketCategory>> categoriesGroupByPid = new HashMap<>();
        for (MarketCategory category : marketCategories) {
            Integer pid = category.getPid();
            List<MarketCategory> list = categoriesGroupByPid.get(pid);
            if (list == null) {
                list = new ArrayList<>();
                categoriesGroupByPid.put(pid, list);
            }
            list.add(category);
        }
        return categoriesGroupByPid;
    }
}
